﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using Auction_Intranet.Models;
using AuctionDataLayer;

namespace Auction_Intranet.Controllers
{
    [HandleError]
    public class GroupsController : ParentController
    {
        DataRepository m_rep = new DataRepository();

        public ActionResult Index()
        {
            var username = (User.Identity.Name).Split('\\')[1];
            var user = m_rep.GetUserByUsername(username);
            List<UserGroupModel> model = new List<UserGroupModel>();
            if(user != null)
            {
                var userGroups = m_rep.GetGroupsByUserId(user.Id);
                foreach (var item in userGroups)
                {
                    UserGroupModel tempGroup = new UserGroupModel();
                    tempGroup.group = item;
                    tempGroup.groupMembers = m_rep.GetMembersOfGroupById(item.Id);
                    tempGroup.numberOfBids = m_rep.GetBidsByGroupId(item.Id).Count();
                    tempGroup.numberOfPendingInvitations = m_rep.GetPendingInvitationsByGroupId(item.Id).Count();
                    model.Add(tempGroup);
                }
            }
            return View(model);
        }

        public ActionResult UserInfo(int? id, int? groupid)
        {
            if (id.HasValue && groupid.HasValue)
            {
                int realUserId = id.Value;
                int realGroupId = groupid.Value;
                
                var username = (User.Identity.Name).Split('\\')[1];
                var user = m_rep.GetUserByUsername(username);
                
                var groupmembers = m_rep.GetUsersInGroupById(realGroupId);
                var me = groupmembers.Where(x => x.UserId == user.Id).SingleOrDefault();
                var member = groupmembers.Where(x => x.UserId == realUserId).SingleOrDefault();
                if (me != null && member != null)
                {
                    User model = m_rep.GetUserById(realUserId);
                    if (model != null)
                    {
                        return View(model);
                    }
                }
            }
            return View("NotFound");
        }

        public ActionResult RemoveInvitation(int? id)
        {
            if (id.HasValue)
            {
                int realId = id.Value;
                Invitation model = m_rep.GetInvitaionById(realId);
                if (model != null)
                {
                    int groupId = model.GroupId;
                    m_rep.RemoveInvitation(model);
                    var groupPendingInvitataion = m_rep.GetPendingInvitationsByGroupId(groupId);
                    if (groupPendingInvitataion.Count() > 0)
                    {
                        return RedirectToAction("PendingInvitations", new { id = groupId });
                    }
                    else
                    {
                        return RedirectToAction("Index");
                    }
                }
            }
            return View("NotFound");
        }

        public ActionResult PendingInvitations(int? id)
        {
            if (id.HasValue)
            {
                int realId = id.Value;
                var group = m_rep.GetGroupById(realId);
                var pendingInvitations = m_rep.GetPendingInvitationsByGroupId(realId);
                GroupInvitationsModel model = new GroupInvitationsModel();
                model.group = group;
                model.groupInvitations = pendingInvitations;
                return View(model);
            }
            return View("NotFound");
        }

        public ActionResult GroupBids(int? id)
        {
            if (id.HasValue)
            {
                int realId = id.Value;
                var group = m_rep.GetGroupById(realId);
                if (group != null)
                {
                    var result = m_rep.GetBidsByGroupId(realId);
                    GroupBidsModel model = new GroupBidsModel();
                    BidsListModel bids = new BidsListModel();
                    bids.userBids = result;
                    bids.pendingBids = result.Where(x => x.StateId == 1).Count();
                    bids.acceptedBids = result.Where(x => x.StateId == 2).Count();
                    bids.declinedBids = result.Where(x => x.StateId == 3).Count();

                    model.group = group;
                    model.groupBids = bids;
                    return View(model);
                }               
                return View();
            }
            return View("NotFound");
        }      

        public ActionResult Invite(int? id)
        {
            if (id.HasValue)
            {  
                int realId = id.Value;
                var group = m_rep.GetGroupById(realId);
                if(group != null)
                {
                    InviteGroupMemberModel model = new InviteGroupMemberModel();
                    model.groupId = group.Id;
                    model.groupName = group.Name;
                    return View(model);
                }
                return View("Error");
            }
            return View("NotFound");
        }

        [HttpPost]
        public ActionResult Invite(InviteGroupMemberModel model)
        {
            if (ModelState.IsValid)
            {
                //Need to check if already is a member in group
                if (model.groupMember != null && (!isUsernameValid(model.groupMember)))
                {
                    ModelState.AddModelError("groupMember", "Member to add field is invalid.");
                    return View(model);
                }
                //Todo: If member does exist but has not signed in yet. Account has to be made to be able to send invitation.
                var member = m_rep.GetUserByUsername(model.groupMember);
                if (member != null)
                {
                    m_rep.AddInvitation(member.Id, model.groupId);
                    return RedirectToAction("Index");
                }
                else {                   
                    HRStudents_ possibleUser = m_rep.getRUUserByUserName(model.groupMember);
                    if (possibleUser != null)
                    {
                        //Create member
                        User newUser = m_rep.getOrCreateRUUserByUserName(possibleUser.sUser);
                        m_rep.AddNewUserForAuction(newUser);

                        //Create a group for this user only  
                        Group group = new Group();
                        group.Created = DateTime.Now;
                        group.Name = newUser.Username;
                        group.Balance = newUser.Balance;
                        m_rep.CreateNewSingleGroup(group);

                        //Add him to his group 
                        UserInGroup userInGroup = new UserInGroup();
                        userInGroup.UserId = newUser.Id;
                        userInGroup.GroupId = group.Id;
                        userInGroup.CreditAdded = newUser.Balance;
                        userInGroup.ActiveMember = true;
                        m_rep.AddMemberToSingleGroup(userInGroup);

                        m_rep.UpdadeUserSingleGroupId(newUser.Id, group.Id);

                        //Add invitation
                        m_rep.AddInvitation(newUser.Id, model.groupId);
                        return RedirectToAction("Index");
                    }
                }
                return View("Error");
            }
            return View(model);
        }

        public ActionResult Leave(int? id)
        {
            if (id.HasValue)
            {
                int realId = id.Value;
                var group = m_rep.GetGroupById(realId);
                var username = (User.Identity.Name).Split('\\')[1];
                var user = m_rep.GetUserByUsername(username);
                if (group != null && user != null)
                {
                    LeaveGroupModel model = new LeaveGroupModel();
                    model.group = group;
                    UserInGroup userInGroup = m_rep.GetUserInGroupById(user.Id,group.Id);
                    model.balanceAvailable = userInGroup.CreditAdded - userInGroup.CreditAddedSpent;

                    List<UserInGroupBid> UserIngGroupBids = m_rep.GetAllUserInGroupBidsForUserInGroup(userInGroup.Id,group.Id).ToList();
                    model.balanceInvested = UserIngGroupBids.Sum(x => x.MembersCreditPaid);
                    return View(model);
                }
            }
            return View("NotFound");
        }

        [HttpPost, ActionName("Leave")]
        public ActionResult LeaveConfirm(int? id)
        {
            if (id.HasValue)
            {
                var username = (User.Identity.Name).Split('\\')[1];
                var user = m_rep.GetUserByUsername(username);
                int realId = id.Value;
                var group = m_rep.GetGroupById(realId);
                if (user != null && group != null)
                {
                    var userInGroup = m_rep.GetUserInGroupById(user.Id, group.Id);
                    if (userInGroup != null)
                    {
                        var refund = userInGroup.CreditAdded - userInGroup.CreditAddedSpent;

                        //Update userInGroup
                        m_rep.UpdateUserInGroupSpent(refund, user.Id, group.Id);
                        m_rep.UpdateUserInGroupStatus(false, user.Id, group.Id);
                        //Update userbalance 
                        m_rep.UpdateGroupBalance(user.Balance + refund, user.MyGroupId);
                        m_rep.UpdateUserBalance(user.Balance + refund, user.Id);
                        m_rep.UpdateUserInGroupRefund(refund, user.Id, user.MyGroupId);
                        //UpdateGroupBalance
                        m_rep.UpdateGroupBalance(group.Balance - refund, group.Id);
                        return RedirectToAction("Index");
                    }

                   // m_rep.DeleteUserFromGroup(user.Id, realId);
                    
                }
                return View("Error");
            }
            return View("NotFound");
        }

        public ActionResult AddCredit(int? id)
        {
            if (id.HasValue)
            {
                var username = (User.Identity.Name).Split('\\')[1];
                var user = m_rep.GetUserByUsername(username);
                if (user != null)
                {
                    int realId = id.Value;
                    var realModel = m_rep.GetUserInGroupById(user.Id, realId);
                    AddCreditModel model = new AddCreditModel();
                    model.userId = realModel.UserId;
                    model.groupId = realModel.GroupId;
                    model.groupName = realModel.Group.Name;
                    model.userCredit = realModel.User.Balance;
                    
                    return View(model);
                }
                return View("Error");
 
            }
            return View("NotFound");
        }

        [HttpPost]
        public ActionResult AddCredit(AddCreditModel model)
        {
            if (ModelState.IsValid)
            {
                var username = (User.Identity.Name).Split('\\')[1];
                var user = m_rep.GetUserByUsername(username);
                var group = m_rep.GetGroupById(model.groupId);
                
                if(user != null && group != null)
                {
                    if (model.creditAdded <= 0 || model.creditAdded > user.Balance)
                    {
                        ModelState.AddModelError("", "Invalid bidding amount");
                        return View(model);
                    } 
                    //Update SingleGroupBalance
                    m_rep.UpdateGroupBalance(user.Balance - model.creditAdded, user.MyGroupId);
                    //Update SingleGroupUserInGroup Balance
                    m_rep.UpdateUserInGroupSpent(model.creditAdded, user.Id, user.MyGroupId);
                    //Update UsersBalance
                    m_rep.UpdateUserBalance(user.Balance - model.creditAdded, user.Id);
                    

                    m_rep.AddCreditToUserInGroup(model.creditAdded, user.Id, group.Id);
                    m_rep.UpdateGroupBalance(group.Balance + model.creditAdded,group.Id);                                                          
                    return RedirectToAction("Index");                   
                }
                return View("Error");
            }
            return View(model);
        }

        private bool isUsernameValid(string member)
        {
            var username = (User.Identity.Name).Split('\\')[1];
            User user = m_rep.GetUserByUsername(username);
            var memberToAdd = m_rep.getRUUserByUserName(member);
            if (user != null && memberToAdd != null)
            {
                var exists = user.Username != memberToAdd.sUser;
                if (exists)
                {
                    return true;
                }
            }
            return false;
        }

        public ActionResult CheckUsername(string query, int? id)
        {
            //Todo check if user is already a member already has a pending invitation
            //we want all exept his own 
            if (id.HasValue)
            {
                int realId = id.Value;
                var username = (User.Identity.Name).Split('\\')[1];
                Group group = m_rep.GetGroupById(realId);
                var memberToAdd = m_rep.getRUUserByUserName(query);
                if (group != null && memberToAdd != null) 
                {
                    List<string> groupMembers = m_rep.GetPendingInvitationsByGroupId(realId).Select(x => x.User.Username).ToList();
                    groupMembers.Concat<string>(m_rep.GetMembersOfGroupById(realId).Select(x => x.User.Username).ToList());
                    groupMembers.Add(username);
                    var memberIsInGroup = groupMembers.Contains(memberToAdd.sUser);

                    if (!memberIsInGroup)
                    {
                        return Json(1);
                    }
                }
            }
            return Json("");
        }

        //TODO : Parse string before sending to db. sql injections
        public ActionResult CollectUsernames(string query, int? id)
        {
            if (id.HasValue)
            {
                int realId = id.Value;
                //we want all exept his own 
                var username = (User.Identity.Name).Split('\\')[1];
                //User user = m_rep.GetUserByUsername(username);
                Group group = m_rep.GetGroupById(realId);
                if (group != null && username != null)
                {
                    List<string> groupMembers = m_rep.GetPendingInvitationsByGroupId(realId).Select(x => x.User.Username).ToList();
                    groupMembers.Concat<string>(m_rep.GetMembersOfGroupById(realId).Select(x => x.User.Username).ToList());
                    groupMembers.Add(username);
                    var users = m_rep.GetAllUsernamesExceptGroupMembersFiltered(groupMembers, query);
                    List<object> results = new List<object>();
                    foreach (var item in users)
                    {
                        var temp = new { username = item.sUser, name = item.sName };
                        results.Add(temp);
                    }
                    return Json(results, JsonRequestBehavior.AllowGet);
                }                
            }
            return Json("", JsonRequestBehavior.AllowGet);
        }
    }
}
